package com.xinqi.modules.exam.student.manager.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.xinqi.common.base.enums.YesNoEnum;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.modules.exam.paper.dto.rsp.CourseExamPaperStatsDataDTO;
import com.xinqi.modules.exam.student.domain.CourseExamPaperStudentEntity;
import com.xinqi.modules.exam.student.dto.req.CourseExamPaperStudentQueryDTO;
import com.xinqi.modules.exam.student.dto.rsp.CourseExamPaperStudentListDTO;
import com.xinqi.modules.exam.student.dto.rsp.CourseExamPaperStudentResultDTO;
import com.xinqi.modules.exam.student.enums.PaperAnswerStatusEnum;
import com.xinqi.modules.exam.student.manager.CourseExamPaperStudentManager;
import com.xinqi.modules.exam.student.mapper.CourseExamPaperStudentMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 课程测评学生答题管理层实现
 *
 * @author: linkai
 * @date: 2023/07/02
 */
@Service
@RequiredArgsConstructor
public class CourseExamPaperStudentManagerImpl extends BaseServiceImpl<CourseExamPaperStudentMapper, CourseExamPaperStudentEntity> implements CourseExamPaperStudentManager {

    /**
     * 自定义分页查询
     */
    @Override
    public Page<CourseExamPaperStudentResultDTO> findPage(Page<Object> page, CourseExamPaperStudentQueryDTO query) {
        return this.baseMapper.findPage(page, query);
    }

    /**
     * 自定义列表查询
     */
    @Override
    public List<CourseExamPaperStudentResultDTO> findList(CourseExamPaperStudentQueryDTO query) {
        return this.baseMapper.findList(query);
    }

    /**
     * 根据id查询 课程测评学生答题数据
     */
    @Override
    public CourseExamPaperStudentEntity findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return getById(id);
    }

    /**
     * 根据id更新 课程测评学生答题数据，重写
     */
    @Override
    public boolean updateById(CourseExamPaperStudentEntity entity) {
        return SqlHelper.retBool(getBaseMapper().updateById(entity));
    }

    /**
     * 根据id删除 课程测评学生答题数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return this.removeById(id);
    }

    @Override
    public CourseExamPaperStudentEntity findByExamIdAndStudentId(Long examId, Long studentId) {
        if (examId == null || studentId == null) {
            return null;
        }
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        wrapper.eq(CourseExamPaperStudentEntity::getStudentId, studentId);
        return getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRejectPaper(Long examId, List<Long> studentIdList) {
        if (examId == null || CollectionUtils.isEmpty(studentIdList)) {
            return false;
        }
        return this.baseMapper.updateRejectPaper(PaperAnswerStatusEnum.被打回.getCode(), examId, studentIdList) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateRejectPaperByIds(List<Long> studentPaperIdList) {
        if (CollectionUtils.isEmpty(studentPaperIdList)) {
            return false;
        }
        return this.baseMapper.updateRejectPaperByIds(PaperAnswerStatusEnum.被打回.getCode(), studentPaperIdList) > 0;
    }

    @Override
    public List<Long> findStudentIdByNotPaper(Long examId) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CourseExamPaperStudentEntity::getStudentId);
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        wrapper.eq(CourseExamPaperStudentEntity::getIsSubmit, YesNoEnum.NO.ordinal());
        return this.list(wrapper).stream().map(CourseExamPaperStudentEntity::getStudentId).collect(Collectors.toList());
    }

    @Override
    public List<CourseExamPaperStudentEntity> findByExamId(Long examId) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        return list(wrapper);
    }

    @Override
    public boolean isAllMark(Long examId) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        wrapper.eq(CourseExamPaperStudentEntity::getIsMarked, YesNoEnum.NO.ordinal());
        return this.count(wrapper) == 0;
    }

    @Override
    public boolean isGenerated(Long examId) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        wrapper.eq(CourseExamPaperStudentEntity::getIsDelete, YesNoEnum.NO.ordinal());
        return this.count(wrapper) > 0;
    }

    @Override
    public List<CourseExamPaperStudentListDTO> findStudentList(CourseExamPaperStudentQueryDTO dto) {
        return this.baseMapper.findStudentList(dto);
    }

    @Override
    public IPage<CourseExamPaperStudentListDTO> pageStudentList(Page<Object> page, CourseExamPaperStudentQueryDTO dto) {
        return this.baseMapper.pageStudentList(page, dto);
    }


    @Override
    public CourseExamPaperStudentEntity findRandStudent(Long examId) {
        return this.baseMapper.findRandStudent(examId);
    }

    @Override
    public CourseExamPaperStatsDataDTO findStats01(Long examId) {
        return this.baseMapper.findStats01(examId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateNotCommitPaperStatus(Long examId) {
        LambdaUpdateWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaUpdateWrapper<>();
        // 查询
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        wrapper.eq(CourseExamPaperStudentEntity::getIsSubmit, YesNoEnum.NO.ordinal());
        // 赋值
        wrapper.set(CourseExamPaperStudentEntity::getIsSubmit, YesNoEnum.YES.ordinal());
        wrapper.set(CourseExamPaperStudentEntity::getIsForceSubmit, YesNoEnum.YES.ordinal());
        wrapper.set(CourseExamPaperStudentEntity::getIsMarked, YesNoEnum.YES.ordinal());
        wrapper.set(CourseExamPaperStudentEntity::getIsSysMarked, YesNoEnum.YES.ordinal());
        wrapper.set(CourseExamPaperStudentEntity::getStatus, PaperAnswerStatusEnum.已批阅.getCode());
        wrapper.set(CourseExamPaperStudentEntity::getScore, 0);
        wrapper.set(CourseExamPaperStudentEntity::getQuestionRightNum, 0);
        return update(null, wrapper);
    }

    /**
     * 查询需要打回的试卷的学生ID
     */
    @Override
    public List<Long> findRejectPaper(Long examPaperId, List<Long> studentIdList) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CourseExamPaperStudentEntity::getStudentId);
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examPaperId);
        wrapper.in(CourseExamPaperStudentEntity::getStudentId, studentIdList);
        wrapper.eq(CourseExamPaperStudentEntity::getIsSubmit, YesNoEnum.YES.ordinal());
        return list(wrapper).stream().map(CourseExamPaperStudentEntity::getStudentId).collect(Collectors.toList());
    }

    @Override
    public List<Long> findStudentIdByExamId(Long examId) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CourseExamPaperStudentEntity::getStudentId);
        wrapper.eq(CourseExamPaperStudentEntity::getExamPaperId, examId);
        return list(wrapper).stream().map(CourseExamPaperStudentEntity::getStudentId).collect(Collectors.toList());
    }

    @Override
    public Boolean deleteByUserIds(List<Long> userIdList) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CourseExamPaperStudentEntity::getIsDelete, YesNoEnum.NO.ordinal());
        wrapper.in(CourseExamPaperStudentEntity::getStudentId, userIdList);
        return remove(wrapper);

    }

    @Override
    public List<Long> findExamIdByStudentId(List<Long> userIdList) {
        LambdaQueryWrapper<CourseExamPaperStudentEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(CourseExamPaperStudentEntity::getIsDelete, YesNoEnum.NO.ordinal());
        wrapper.in(CourseExamPaperStudentEntity::getStudentId, userIdList);
        return list(wrapper).stream().map(v -> v.getExamPaperId()).collect(Collectors.toList());
    }

}
